package videopath

import (
	"bytes"
	"encoding/binary"
	"fmt"
	//"github.com/go-fsnotify/fsnotify"
	"os"
	//"io/ioutil"
	//"bufio"
	"ktvserver/ktvutil"
	"log"
	"path/filepath"
	"unicode/utf16"
	//"strings"
	"sync"
	//"syscall"
	"time"
)

var (
	mu sync.Mutex //

	HasLoadVideoPathCfg = false
	songVideoPath       map[uint32]string
	VideoPathDataFile   = filepath.Join("SYSTEM", "VIDEOPATH.DB")

	lastUpdateDate int64
)

// 歌曲编号记录
type NumberToPath struct {
	SongNum uint32 // 歌曲编号
	Offset  uint32 // 偏移位置
}

func init() {
	HasLoadVideoPathCfg = false
	songVideoPath = make(map[uint32]string)

}

// 清空歌曲视频文件路径
func clearSongVideoPath() {

	for key := range songVideoPath {
		delete(songVideoPath, key)
	}

	HasLoadVideoPathCfg = false

}

func InitSongVideoPath() {
	reloadSongVideoPath()
}

func ReloadSongVideoPath() {

	if time.Now().Unix() <= lastUpdateDate+3 {
		return
	}

	reloadSongVideoPath()

}

func reloadSongVideoPath() {

	lastUpdateDate = time.Now().Unix()

	// 读取全部的数据到内存
	f, err := os.Open(VideoPathDataFile)
	//data, err := ioutil.ReadFile(VideoPathDataFile)
	if err != nil {
		return
	}

	defer f.Close()

	fi, _ := f.Stat()

	if fi.Size() <= 0 {
		return
	}

	data := make([]byte, fi.Size())
	f.Read(data)

	rd := bytes.NewReader(data)

	// 分析数据开始
	//copyright := ktvutil.GetCopyrightInfo(data)
	var copyright ktvutil.DatCopyright

	binary.Read(rd, binary.LittleEndian, &copyright)

	if copyright.IsShiyou() != true {
		return
	}

	// 添加路径到map
	var i uint32
	var countAll int

	//fmt.Printf("VideoPath RecordCount = %d\n", copyright.RecordCount)

	for i = 0; i < copyright.RecordCount; i++ {

		recordOffset := ktvutil.GetCopyrightStructLength() + i*8
		// 检查是否越界
		if recordOffset >= uint32(fi.Size()) {
			break
		}

		// 偏移到指定的位置, 读取NumberToPath记录
		rd.Seek(int64(recordOffset), 0)

		var np NumberToPath
		binary.Read(rd, binary.LittleEndian, &np)

		if np.Offset >= uint32(fi.Size()) {
			break
		}

		//fmt.Printf("number = %d, offset = %d\n", np.SongNum, np.Offset)

		// 读取视频文件路径
		vp := []uint16{}

		rd.Seek(int64(np.Offset), 0)

		for j := 0; j < 250; j++ {
			var ch uint16
			binary.Read(rd, binary.LittleEndian, &ch)
			if ch == 0 {
				break
			}
			vp = append(vp, ch)

		} // end for

		videoPath := UTF16ToString(vp)

		songVideoPath[np.SongNum] = videoPath

		//if np.SongNum >= 720000 && np.SongNum <= 720010 {
		//	fmt.Printf("videopath, %d=%s\n", np.SongNum, videoPath)
		//}
		//
		countAll++

	}

	log.Printf("VideoPath Count = %d\n", countAll)

}

// 获取歌曲视频文件路径
func GetSongVideoPath(number uint32, ext []uint16) string {

	mu.Lock()
	defer mu.Unlock()

	// 检查在map中是否存在
	videopath, exists := songVideoPath[number]
	if exists {
		//log.Printf("video path found, %d = %s\n", number, videopath)
		return videopath
	} else {
		log.Printf("video path not found, %d\n", number)
	}

	// 如果文件不存在，则直接生成一段记录
	//strExt := syscall.UTF16ToString(ext)
	//videopath = fmt.Sprintf("SONG", ...)

	videopath = filepath.Join("SONG",
		fmt.Sprintf("%02d", number%100),
		fmt.Sprintf("%d", number),
		"1234561")

	absPath, _ := filepath.Abs(videopath)
	return absPath
}

// 获取公共下载歌曲文件夹地址
func GetPublicSongFolder(number uint32) string {

	mu.Lock()
	defer mu.Unlock()

	// 检查在map中是否存在
	videopath, exists := songVideoPath[number]
	if exists {
		// 去除视频文件路径后面的1234561
		//log.Printf("video path found2, %d = %s\n", number, videopath)
		folderPath := filepath.Dir(videopath)
		return folderPath
	} else {
		log.Printf("video path not found, %d \n", number)
	}

	videopath = filepath.Join("SONG",
		fmt.Sprintf("%02d", number%100),
		fmt.Sprintf("%d", number),
		"1234561")

	absPath, _ := filepath.Abs(videopath)
	return filepath.Dir(absPath)
}

// UTF16ToString returns the UTF-8 encoding of the UTF-16 sequence s,
// with a terminating NUL removed.
func UTF16ToString(s []uint16) string {
	for i, v := range s {
		if v == 0 {
			s = s[0:i]
			break
		}
	}
	return string(utf16.Decode(s))
}
